#!/usr/bin/perl -w

use strict;
use warnings;
use Data::Dumper;
use Getopt::Long;

require "utils.pl";

use constant {
		VERSION => 0.010
		};

my $seq_file = ''; # file with the sequence of DNA or RNA to fold
my $zones_file = '' ; #file with the zones
my $initial_temp = 35; # initial temperature
my $final_temp = 41; # final temperature
my $help_required = 0;
my $must_not_run_mfold; # prevent to run mfold
my $complement; # whether to compute the complement of the sequenece in $seq_file or not
my $must_not_package; # prevent to compress and remove 
my $not_run_parser_det; # prevent to compress and remove 
&main();

sub print_help_and_exit {
    my $prog_name = shift;
    print STDERR "Usage: $prog_name --seq=file --zones=file [--itemp=temp] [--ftemp=temp] [--help]\n\n";

    print STDERR
        "\t--seq=file\tfolds the RNA or DNA sequence in `file'.\n".
        		"\t\t\tThis parameter is mandatory.\n".
        "\t--zones=file\tholds the zones to process. This file contains \n".
        		"\t\t\tlines of the form:\n".
                "\t\t\t\`zone_name, initial_nucleotide, final_nucleotide'\n".
        		"\t\t\tThis parameter is mandatory.\n".
        "\t--itemp=n\tuse `n' as initial temperature (in celsius) to compute\n".
        		"\t\t\tthe foldings.\n".
        		"\t\t\tThis parameter will be passed to the `T' parameter\n".
        		"\t\t\tof mfold. This parameter is optional\n".
        		"\t\t\tand defaults to 35.\n".
        "\t--ftemp=m\tuse `m' as final temperature. Defaults to 41 and is optional.\n".
        "\t--compl\t\tProcess also the complement folding.\n".
        "\t--notfold\tPrevents the script to run mfold.\n".
        "\t--notpakage\tPrevents the script to package the results.\n".
        "\t--notparse\tPrevents the script to call the det_parser.\n".
        "\t--help\t\tprints this help and exits.\n";

    exit;
}


sub read_zones_file{

	# An array to hold the zones. The structure is:
    # (zone_name1, initial_nucleotide1, final_nucleotide1, zone_name2, initial_nucl2, final_nucl2, etc)
    my $zones_arr = shift;

    my $file_name = shift;

    my @zones;

    open(FH, $file_name) or die "Can not open `$file_name': $!\n";

    @zones = <FH>;

    foreach my $line (@zones){
        chomp $line;

	# match a line of the form:
        # zone_name, init_nucleotide, final_nucleotide
	# and stores the values in $1, $2 and $3
        if ($line =~ m/^\s*(.*?)\s*,\s*(\d+)\s*,\s*(\d+).*$/){
	    
            if ( ($2 >= $3 and $3 != 0)){
                die "malformed line \"$line\"!!\n";
            }
	    

            my @tmp_arr = ($1, $2, $3);
            push(@$zones_arr, @tmp_arr);
            
        } elsif ($line =~ m/\s*/) {
            # linea vacia: skip
        } else {
            die "invalid line \"$line\"!\n";
        }
    }
    
    close(FH);
}



###########################################

sub calc_structure
{
    my ($ct_names)=@_;

    foreach my $name_seq (@$ct_names)
    {
        # run mfold iff --notfold was NOT specified in the command line
        run_mfold($initial_temp, $final_temp, $name_seq) unless (defined ($must_not_run_mfold));
    }
	
    return;
}


sub ct_analyzer
{
    my ($ct_names,$zones_array,$result_name)=@_;

    my $HANDLERESULTS;
	
	open_file(">$$result_name",\$HANDLERESULTS);

	print_header($zones_array,$HANDLERESULTS);
    
	foreach my $name_seq (@$ct_names)
    {
        for(my $temp = $initial_temp; $temp <= $final_temp; $temp++)
        {
            my $det_file=$temp."/".$name_seq."_".$temp."\.det";
            my $ct_file=$temp."/".$name_seq."_".$temp."_1.ct";
            my $ss_file=$temp."/".$name_seq."_".$temp.".ss-count";
            #my $arrayNucleoApp=$temp;
	    my ($total,$energy)=get_data_header_file($ct_file);
            my $arrayNucleoApp=$temp.",".$energy;
 	     make_zones(\$ct_file,\$ss_file,\$arrayNucleoApp,$zones_array,\$det_file,$total);  
            print $HANDLERESULTS "$arrayNucleoApp\n";
        }

        print $HANDLERESULTS "-"x100; 
	print $HANDLERESULTS "\n";

    }
	
    return ;
}

##########################################################
sub make_zones
{

my ($ct_file,$ss_file,$arrayNucleoApp,$zones_array,$det_file,$total)=@_;

 my $last_index = scalar(@$zones_array)-1;

	
	for(my $zone_name_index = 0; $zone_name_index < $last_index; $zone_name_index += 3)
            {
                my $nucleo_app;
                my $ss_score=0;
				my $init_zone=$$zones_array[$zone_name_index+1];
			   my $end_zone=$$zones_array[$zone_name_index+2];
		#my ($total,$energy)=get_data_header_file($$ct_file);
		# translate zone boundaries for the complementary
		if ($$ct_file =~ m/\_compl/)
		{ 
			#my ($total,$energy)=get_data_header_file($$ct_file);

			if ($end_zone == 0)
			{
				$init_zone=1;
			}
			else
			{
				$init_zone=$total-$end_zone+1;
				$end_zone=$total-$$zones_array[$zone_name_index+1]+1;
			}

		}
			  my $newEnergy=0; 
			   get_energy($det_file,\$newEnergy,$init_zone,$end_zone,$not_run_parser_det);
                	read_nucleotidos_apareaos($ct_file,\$nucleo_app,$init_zone,$end_zone);
                	sum_zone_no_apareados($ss_file,\$ss_score,$init_zone,$end_zone);
			$$arrayNucleoApp=join(',',$$arrayNucleoApp,$$zones_array[$zone_name_index],$newEnergy,$nucleo_app,$ss_score);
            }

}
####################################
sub print_header
{
 my ($zones_array,$HANDLERESULT)=@_;
 my $last_index = scalar(@$zones_array)-1;
	my $print_head="TEMP(Celsius),ENERGIA_DEL_CT";
	for(my $zone_name_index = 0; $zone_name_index < $last_index; $zone_name_index += 3)
	{
		my $index=($zone_name_index / 3)+1;
		$print_head=join (',',$print_head,"NOM_ZONA_$index","ENERGIA_CALCULADA_$index","NUC_APAREADOS_$index","SS-SCORE_$index");
	}


	print $HANDLERESULT "$print_head\n";
}



sub main{

    GetOptions('seq=s'   => \$seq_file,
               'zones=s' => \$zones_file,
               'itemp=i' => \$initial_temp,
               'ftemp=i' => \$final_temp,
               'compl'   => \$complement,
               'notfold' => \$must_not_run_mfold,
	       'notpackage' => \$must_not_package,
	       'notparse' => \$not_run_parser_det,
               'help'    => \$help_required);


    print STDERR "$0 version ".VERSION."\n";

    if ($help_required or $zones_file eq '' or
#        this will be the right check when the seq file becomes optional
#        ($seq_file eq '' and !defined ( $must_not_run_mfold ) ) )
        $seq_file eq '' )
    {
        print_help_and_exit($0);
    }

    my @ct_names;
    $seq_file =~ m/\.seq$/;
    $ct_names[0]=$`;

    if ( defined ($complement) )
    {
        $ct_names[1]=$ct_names[0]."_compl";
        make_complementary($ct_names[0],$ct_names[1]);
    }

    calc_structure(\@ct_names);

    # An array to hold the zones. Refer to
    # sub read_zones_file to know the internal structure
    my @zones;

    read_zones_file(\@zones, $zones_file);
    my $results_name=$ct_names[0]."\.results";
    ct_analyzer(\@ct_names,\@zones,\$results_name);

   	pack_results($initial_temp,$final_temp, $ct_names[0],$results_name,$complement) unless (defined ($must_not_package));

}

